
package Math;

import Math.Matrix;

/* Start of 'Vector' class */
public class Vector
{
  /* Vector coordinates */
  public double X, Y, Z;

  /* 'Vector' class default constructor
   * ARGUMENTS: None.
   * RETURNS: None.
   */
  public Vector( )
  {
  } /* End of 'Vector' class constructor */

  /* 'Vector' class constructor
   * ARGUMENTS:
   *   - vector same coordinate
   *       double N;
   * RETURNS: None.
   */
  public Vector( double N )
  {
    X = Y = Z = N;
  } /* End of 'Vector' class constructor */

  /* 'Vector' class constructor
   * ARGUMENTS:
   *   - vector coordinates
   *       double X, Y, Z;
   * RETURNS: None.
   */
  public Vector( double x, double y, double z )
  {
    X = x;
    Y = y;
    Z = z;
  } /* End of 'Vector' class constructor */

  /* 'Vector' class copy constructor
   * ARGUMENTS:
   *   - copying vector
   *       Vector V;
   * RETURNS: None.
   */
  public Vector( Vector V )
  {
    X = V.X;
    Y = V.Y;
    Z = V.Z;
  } /* End of 'Vector' class constructor */

  /* Convert vector to string
   * ARGUMENTS: None.
   * RETURNS: None.
   */
  public String toString( )
  {
    return Double.toString(X) + " " + Double.toString(Y)
           + " " + Double.toString(Z);
  } /* End of 'toString' function */

  /* Vec add vec
   * ARGUMENTS:
   *   - adding vector
   *       Vector V;
   * RETURNS:
   *   - vecotr sum
   *       Vector;
   */
  public Vector AddVec( Vector V )
  {
    return new Vector(X + V.X, Y + V.Y, Z + V.Z);
  } /* End of 'AddVec' function */

  /* Vec self add vec
   * ARGUMENTS:
   *   - adding vector
   *       Vector V;
   * RETURNS:
   *   - reference to self
   *       Vector;
   */
  public Vector AddVecSelf( Vector V )
  {
    X += V.X;
    Y += V.Y;
    Z += V.Z;

    return this;
  } /* End of 'AddVecSelf' function */

  /* Vec sub vec
   * ARGUMENTS:
   *   - subbing vector
   *       Vector V;
   * RETURNS:
   *   - vecotr difference
   *       Vector;
   */
  public Vector SubVec( Vector V )
  {
    return new Vector(X - V.X, Y - V.Y, Z - V.Z);
  } /* End of 'AddVec' function */

  /* Vec self sub vec
   * ARGUMENTS:
   *   - subbing vector
   *       Vector V;
   * RETURNS:
   *   - reference to self
   *       Vector;
   */
  public Vector SubVecSelf( Vector V )
  {
    X -= V.X;
    Y -= V.Y;
    Z -= V.Z;

    return this;
  } /* End of 'SubVecSelf' function */

  /* Scalar vecotr product
   * ARGUMENTS:
   *   - scalar product vecotr
   *       Vector V;
   * RETURNS:
   *   - scalar vecotr product
   *       double;
   */
  public double DotVec( Vector V )
  {
    return X * V.X + Y * V.Y + Z * V.Z;
  } /* End of 'DotVec' function */

  /* Vector production of vectors
   * ARGUMNETS:
   *   - vector product vector
   *       Vector V;
   * RETURNS:
   *   - vector production
   *       Vector;
   */
  public Vector CrossVec( Vector V )
  {
    return new Vector(Y * V.Z - Z * V.Y,
                      Z * V.X - X * V.Z,
		      X * V.Y - Y * V.X);
  } /* End of 'CrossVec' function */

  /* Vector self production of vectors
   * ARGUMNETS:
   *   - vector product vector
   *       Vector V;
   * RETURNS:
   *   - reference to self
   *       Vector;
   */
  public Vector CrossVecSelf( Vector V )
  {
    V = this.CrossVec(V);

    X = V.X;
    Y = V.Y;
    Z = V.Z;

    return this;
  } /* End of 'CrossVecSelf' function */


  /* Vector multiply on number
   * ARGUMENTS:
   *   - multiply number
   *       double N;
   * RETURNS:
   *   - result vector
   *       Vector;
   */
  public Vector MulNum( double N )
  {
    return new Vector(X * N, Y * N, Z * N);
  } /* End of 'MulNum' function */

  /* Vector self multiply on number
   * ARGUMENTS:
   *   - multiply number
   *       double N;
   * RETURNS:
   *   - reference to vector
   *       Vector;
   */
  public Vector MulNumSelf( double N )
  {
    X *= N;
    Y *= N;
    Z *= N;
    return this;
  } /* End of 'MulNumSelf' function */

  /* Vector division on number
   * ARGUMENTS:
   *   - division number
   *       double N;
   * RETURNS:
   *   - result vector
   *       Vector;
   */
  public Vector DivNum( double N )
  {
    if (N == 0)
      throw new ArithmeticException("Vector division by zero.");
    return new Vector(X / N, Y / N, Z / N);
  } /* End of 'MulNum' function */

  /* Vector self division on number
   * ARGUMENTS:
   *   - division number
   *       double N;
   * RETURNS:
   *   - reference to vector
   *       Vector;
   */
  public Vector DivNumSelf( double N )
  {
    X /= N;
    Y /= N;
    Z /= N;
    return this;
  } /* End of 'MulDivSelf' function */

  /* Vector length
   * ARGUMENTS: None.
   * RETURNS:
   *   - vector lenght
   *       double;
   */
  public double Len( )
  {
    double Inc = X * X + Y * Y + Z * Z;
    if (Inc != 1 && Inc != 0)
      return Math.sqrt(X * X + Y * Y + Z * Z);
    return Inc;
  } /* End of 'Len' function */

  /* Vector normilize
   * ARGUMENTS: None.
   * RETURNS:
   *   - normilized vector
   *       Vector;
   */
  public Vector Norm( )
  {
    double Inc = X * X + Y * Y + Z * Z;

    if (Inc > 0 && Inc != 1)
      return this.DivNum(Math.sqrt(Inc));
    return new Vector(this);
  } /* End of 'Norm' function */

  /* Vector self normilize
   * ARGUMENTS: None.
   * RETURNS:
   *   - reference to normilized vector
   *       Vector;
   */
  public Vector NormSelf( )
  {
    double Inc = X * X + Y * Y + Z * Z;

    if (Inc > 0 && Inc != 1)
      return this.DivNumSelf(Math.sqrt(Inc));
    return this;
  } /* End of 'NormSelf' function */

  /* Vector mul matrix
   * ARGUMENTS:
   *   - matrix factor
   *       Matrix M;
   * RETURNS:
   *   - vector muled on matrix
   *       Vector;
   */
  public Vector MulMatr( Matrix M )
  {
    return new Vector(X * M.M[0][0] + Y * M.M[1][0] + Z * M.M[2][0] + M.M[3][0],
                      X * M.M[0][1] + Y * M.M[1][1] + Z * M.M[2][1] + M.M[3][1],
		      X * M.M[0][2] + Y * M.M[1][2] + Z * M.M[2][2] + M.M[3][2]);

  } /* End of 'MulMatr' function */

  /* Vector self mul matrix
   * ARGUMENTS:
   *   - matrix factor
   *       Matrix M;
   * RETURNS:
   *   - self reference
   *       Vector;
   */
  public Vector MulMatrSelf( Matrix M )
  {
    Vector V = MulMatr(M);

    X = V.X;
    Y = V.Y;
    Z = V.Z;

    return this;
  } /* End of 'MulMatrSelf' function */

} /* End of 'Vector' class */
